package com.sojson.project.sys.user.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sojson.annotation.Log;
import com.sojson.config.exception.TransErrorCode;
import com.sojson.constant.Constant;
import com.sojson.enums.EEnvironmentUserType;
import com.sojson.enums.core.EBusinessType;
import com.sojson.enums.core.EGeneralStatus;
import com.sojson.enums.core.ELoginDeviceType;
import com.sojson.enums.core.ERoleType;
import com.sojson.project.query.entity.bo.Select;
import com.sojson.project.sys.config.entity.dto.ConfigDto;
import com.sojson.project.sys.role.entity.dto.RoleDto;
import com.sojson.project.sys.role.entity.vo.RoleVo;
import com.sojson.project.sys.role.service.RoleService;
import com.sojson.project.sys.user.controller.param.verify.UserParamVerify;
import com.sojson.project.sys.user.entity.bo.AuthcUser;
import com.sojson.project.sys.user.entity.dto.UserDto;
import com.sojson.project.sys.user.entity.dto.UserPageDto;
import com.sojson.project.sys.user.entity.po.User;
import com.sojson.project.sys.user.entity.vo.UserVo;
import com.sojson.project.sys.user.service.UserService;
import com.sojson.result.Result;
import com.sojson.util.StringUtil;
import com.sojson.util.enums.ELoginOtherType;
import com.sojson.util.poi.ExcelUtil;
import com.sojson.util.token.TokenDto;
import com.sojson.util.token.TokenUtil;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 用户表控制器
 * 
 * @author liu
 * @date 2021-03-16
 */
@Api(tags = "用户表管理")
@RestController
@RequestMapping(value = "/sys/user/user")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;

    /**
     * 短信登录
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @PutMapping("/smsLogin")
    @ApiOperation("短信登录")
    public Result<String> smsLogin(@RequestBody TokenDto dto) throws Exception {
        // 校验参数
        Result<String> paramResult = UserParamVerify.smsLogin(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 参数初始化
        dto.setLoginEnv(EEnvironmentUserType.APP_USER.getCode());
        dto.setLoginType(ELoginOtherType.MOBILE.getCode());
        dto.setTypeLoginDevice(ELoginDeviceType.CELLPHONE.getCode());
        userService.smsLogin(dto);
        // 返回结果
        return Result.success(TokenUtil.getClaimsStr());
    }

    /**
     * 微信小程序登录
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @PutMapping("/wxXcxLogin")
    @ApiOperation("微信小程序登录")
    public Result<String> wxXcxLogin(@RequestBody TokenDto dto) throws Exception {
        // 校验参数
        Result<String> paramResult = UserParamVerify.wxXcxLogin(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 参数初始化
        dto.setLoginEnv(EEnvironmentUserType.XCX_USER.getCode());
        dto.setLoginType(ELoginOtherType.WX_XCX.getCode());
        dto.setTypeLoginDevice(ELoginDeviceType.CELLPHONE.getCode());
        userService.wxXcxLogin(dto);
        // 返回结果
        return Result.success(TokenUtil.getClaimsStr());
    }

    /**
     * 通过id更新
     * 
     * @param dto
     * @return
     * @throws Exception
     */
    @PutMapping("/updateById")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/updateById')")
    @Log(title = "用户信息", businessType = EBusinessType.UPDATE)
    @ApiOperation("通过id更新用户表数据")
    public Result<Boolean> updateById(@RequestBody UserDto dto) throws Exception {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.updateById(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }
        // 权限校验
        List<String> userIds = new ArrayList<>();
        userIds.add(dto.getId());
        userService.isPerm(userIds);

        // 修改信息
        userService.update(dto);
        return Result.success();
    }

    /**
     * 分页查询
     * 
     * @param dto
     * @return
     */
    @GetMapping("/page")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/page')")
    @ApiOperation(value = "分页查询用户表数据", response = UserVo.class)
    public Result<List<UserVo>> page(UserPageDto dto) {
        return Result.success(userService.page(dto));
    }

    /**
     * 导出数据
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @GetMapping("/export")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/export')")
    @Log(title = "用户信息", businessType = EBusinessType.EXPORT)
    @ApiOperation("导出用户表数据")
    public void export(UserDto dto) throws Exception {
        List<UserVo> list = userService.list(dto);
        ExcelUtil<UserVo> excelUtil = new ExcelUtil<>(UserVo.class);
        excelUtil.exportExcelOutFile(list, "用户信息");
    }

    /**
     * 通过id查询
     * 
     * @param id
     * @return
     * @throws Exception 
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/info/{id}')")
    @ApiOperation(value = "通过id查询用户表数据", response = UserVo.class)
    public Result<UserVo> info(@PathVariable String id) throws Exception {
        Result<UserVo> success = Result.success();

        // 获取当前用户的角色ID列表
        Set<String> roleIds = roleService.getRoleIdsByUserId(id);
        // 获取所有角色
        List<RoleVo> list = roleService.list(new RoleDto());
        // 所有角色的ID
        List<String> listIds = list.stream().map(RoleVo::getId).collect(Collectors.toList());

        // 将没有权限的角色去掉
        Iterator<String> iterator = roleIds.iterator();
        while (iterator.hasNext()) {
            String roleId = iterator.next();
            if (listIds.contains(roleId)) {
                continue;
            }
            iterator.remove();
        }
        success.put("roles", list);
        // 超级管理员Key
        success.put("adminSuperKey", ERoleType.ADMIN_SUPER.getKey());

        // 权限校验
        if ("0".equals(id)) {
            return success;
        }

        List<String> userIds = new ArrayList<>();
        userIds.add(id);
        userService.isPerm(userIds);

        UserVo findById = userService.findById(id);
        if (findById == null) {
            return success;
        }
        // 获取用户
        success.setData(findById);
        success.put("roleIds", roleIds);
        return success;
    }

    /**
     * 通过id列表删除
     * 
     * @param dto
     * @return
     * @throws IOException 
     */
    @DeleteMapping("/remove")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/remove')")
    @ApiOperation("通过id列表删除用户表数据")
    public Result<Boolean> remove(@RequestBody ConfigDto dto) throws IOException {
        List<String> ids = dto.getIds();
        if (ids == null || ids.size() == 0) {
            return Result.success();
        }

        // 权限校验
        userService.isPerm(ids);

        userService.removeByIds(ids);
        return Result.success();
    }

    /**
     * 密码重置
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @PutMapping(value = "/resetUserPwd")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/resetUserPwd')")
    @ApiOperation("密码重置")
    public Result<Boolean> resetUserPwd(@RequestBody User dto) throws Exception {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.resetUserPwd(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 权限校验
        List<String> userIds = new ArrayList<>();
        userIds.add(dto.getId());
        userService.isPerm(userIds);

        User u = new User();
        u.setId(dto.getId());
        u.setPwd(dto.getPwd());
        // 修改密码
        return Result.success(userService.resetUserPwd(u));
    }

    /**
     * 通过id修改状态
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @PutMapping("/updateStatus")
    @PreAuthorize("@ss.hasPermi('/sys/user/user/changeStatus')")
    @ApiOperation("通过id修改用户状态")
    public Result<Boolean> updateStatus(@RequestBody User dto) throws Exception {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.updateStatus(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 权限校验
        List<String> userIds = new ArrayList<>();
        userIds.add(dto.getId());
        userService.isPerm(userIds);

        // 修改状态
        User user = new User();
        user.setId(dto.getId());
        user.setStatus(dto.getStatus());
        userService.updateStatus(user);
        return Result.success();
    }

    /**
     * 移动应用绑定微信
     * 
     * @param code 用户授权后的code
     * @return
     * @throws Exception 
     */
    @PutMapping("/wxAppBindOpenid/{code}")
    @PreAuthorize("@ss.login()")
    @ApiOperation("移动应用绑定微信")
    public Result<Boolean> wxAppBindOpenid(@PathVariable String code) throws Exception {
        if (StringUtil.isBlankObject(code)) {
            return Result.fail("code不能为空！");
        }

        // 返回结果
        return Result.success(userService.wxAppBindOpenid(code));
    }

    /**
     * 小程序绑定微信
     * 
     * @param code 用户授权后的code
     * @return
     * @throws Exception 
     */
    @PutMapping("/wxXcxBindOpenid/{code}")
    @PreAuthorize("@ss.login()")
    @ApiOperation("小程序绑定微信")
    public Result<Boolean> wxXcxBindOpenid(@PathVariable String code) throws Exception {
        if (StringUtil.isBlankObject(code)) {
            return Result.fail("code不能为空！");
        }

        // 返回结果
        return Result.success(userService.wxXcxBindOpenid(code));
    }

    /**
     * 通过id更新手机号
     * 
     * @param dto
     * @return
     * @throws Exception 
     */
    @PutMapping(value = "/updateMobileById")
    @PreAuthorize("@ss.hasPermi('/sys/user/updateMobileById')")
    @ApiOperation("通过id更新手机号")
    public Result<Boolean> updateMobileById(@RequestBody TokenDto dto) throws Exception {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.updateMobileById(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 修改手机号
        userService.updateMobileById(dto);
        return Result.success();
    }

    /**
     * 审核认证信息
     * 
     * @param user
     * @return
     */
    @PutMapping(value = "/auditAuth")
    @PreAuthorize("@ss.hasPermi('/user/auditAuth')")
    @ApiOperation("审核认证信息")
    public Result<Boolean> auditAuth(@RequestBody User user) {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.auditAuth(user);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        User mem = new User();
        // 参数初始化
        mem.setId(user.getId());
        mem.setAuthStatus(user.getAuthStatus());
        // 修改信息
        userService.auditAuth(mem);
        return Result.success();
    }

    /**
     * 重置支付密码
     * 
     * @param user
     * @return
     * @throws IOException 
     */
    @PutMapping(value = "/updatePayPwdWeb")
    @PreAuthorize("@ss.hasPermi('/user/updatePayPwdWeb')")
    @ApiOperation("重置支付密码")
    public Result<Boolean> updatePayPwdWeb(@RequestBody AuthcUser user) throws IOException {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.updatePayPwdWeb(user);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 参数初始化
        User mem = new User();
        mem.setId(user.getId());
        String payPwd = user.getPayPwd();
        if (StringUtil.isBlankObject(payPwd)) {
            mem.setPayPwd(Constant.getUserPassword());
        } else {
            mem.setPayPwd(Constant.getUserPassword(user.getPayPwd()));
        }
        // 修改信息
        return Result.success(userService.updateById(mem));
    }

    /**
     * 获取当前佣金信息
     * 
     * @param id
     * @return
     */
    @GetMapping(value = "/findBalance/{id}")
    @PreAuthorize("@ss.hasPermi('/sys/user/findBalance/{id}')")
    @ApiOperation("获取当前佣金信息")
    public Result<UserVo> findBalance(@PathVariable String id) {
        return Result.success(userService.findBalance(id));
    }

    /**
     * 获取当前余额信息
     * 
     * @param id
     * @return
     * @throws IOException 
     */
    @GetMapping(value = "/findBrokerage/{id}")
    @PreAuthorize("@ss.hasPermi('/sys/user/findBrokerage/{id}')")
    @ApiOperation("获取当前余额信息")
    public Result<UserVo> findBrokerage(@PathVariable String id) {
        return Result.success(userService.findBrokerage(id));
    }

    /**
     * 获取下级用户列表
     * 
     * @param user
     * @return
     */
    @GetMapping("/findUnderlingByDto")
    @PreAuthorize("@ss.hasPermi('/user/findUnderlingByDto')")
    @ApiOperation("获取下级用户列表")
    public Result<List<UserVo>> findUnderlingByDto(UserPageDto user) {
        List<UserVo> findByDto = userService.findUnderlingByDto(user);
        return Result.success(findByDto, findByDto);
    }

    /**
     * 获取简历列表
     * 
     * @param user
     * @return
     * @throws IOException 
     */
    @GetMapping("/findResumeList")
    @PreAuthorize("@ss.hasPermi('/user/findResumeList')")
    @ApiOperation("获取简历列表")
    public Result<List<UserVo>> findResumeList(UserPageDto user) throws IOException {
        List<UserVo> findByDto = userService.findResumeList(user);
        return Result.success(findByDto, findByDto);
    }

    /**
     * 获取简历
     * 
     * @param user
     * @return
     * @throws IOException 
     */
    @GetMapping("/findResume")
    @PreAuthorize("@ss.hasPermi('/user/findResume')")
    @ApiOperation("获取简历")
    public Result<UserVo> findResume(String id) throws IOException {
        UserVo findAppResume = userService.findResume(id);
        return Result.success(findAppResume);
    }

    /**
     * 获取简历列表
     * 
     * @param user
     * @return
     * @throws IOException 
     */
    @GetMapping("/findAppResumeList")
    @PreAuthorize("@ss.hasPermi('/user/findAppResumeList')")
    @ApiOperation("获取简历列表")
    public Result<List<UserVo>> findAppResumeList(UserPageDto user) throws IOException {
        List<UserVo> findByDto = userService.findResumeList(user);
        return Result.success(findByDto, findByDto);
    }

    /**
     * 根据对象查询商家列表
     * 
     * @param dto
     * @return
     */
    @GetMapping("/listMferchantApp")
    @ApiOperation("根据对象查询商家列表")
    public Result<List<UserVo>> listMferchantApp(UserPageDto dto) {
        dto.setRoleKey(ERoleType.MERCHANT.getKey());
        dto.setStatus(EGeneralStatus.NORMAL.getCode());
        List<UserVo> list = userService.listByRole(dto);
        for (UserVo user : list) {
            String dist = user.getDist();
            if (StringUtil.isNotBlankObject(dist)) {
                int indexOf = dist.indexOf(".");
                if (indexOf > 0) {
                    user.setDist(dist.substring(0, indexOf));
                }
            }
        }
        return Result.success(list);
    }

    /**
     * 获取下拉列表
     * 
     * @param dto
     * @return
     */
    @GetMapping("/select")
    @ApiOperation("获取用户下拉列表")
    public Result<List<Select>> select(UserPageDto dto) {
        List<Select> list = userService.select(dto);
        return Result.success(list);
    }

    /**
     * 获取用户下拉列表
     * 
     * @param dto
     * @return
     */
    @GetMapping("/selectApp")
    @ApiOperation("获取用户下拉列表")
    public Result<List<Select>> selectApp(UserPageDto dto) {
        dto.setStatus(EGeneralStatus.NORMAL.getCode());
        List<Select> list = userService.select(dto);
        return Result.success(list);
    }

    /**
     * 获取商家下拉列表
     * 
     * @param dto
     * @return
     */
    @GetMapping("/selectMerchant")
    @ApiOperation("获取商家下拉列表")
    public Result<List<Select>> selectMerchant(UserPageDto dto) {
        dto.setRoleKey(ERoleType.MERCHANT.getKey());
        List<Select> list = userService.selectMerchant(dto);
        return Result.success(list);
    }

    /**
     * 用户续租
     * 
     * @param dto
     * @return
     * @throws IOException 
     */
    @PutMapping(value = "/addDayGoOn")
    @PreAuthorize("@ss.hasPermi('/user/update')")
    @ApiOperation("用户续租")
    public Result<Boolean> addDayGoOn(@RequestBody UserDto dto) throws IOException {
        // 校验参数
        Result<Boolean> paramResult = UserParamVerify.addDayGoOn(dto);
        // 验证不通过
        if (!paramResult.getCode().equals(TransErrorCode.SUCCESS.getCode())) {
            return paramResult;
        }

        // 修改信息
        return Result.success(userService.addDayGoOn(dto));
    }

}